"""author: wenyao
   data: 2021/12/9
   project: cjh
"""
#类的定义
#类名：  -- 一般首字母大写 （驼峰命名）

#python2 主流版本-- 2.7
#python3 主流版本--3.6以及之后版本

#python2 -- 经典类和新式类
#       只有显式地继承了object的类称为新式类，其他都是经典类
#python3 -- 新式类
#       默认都是继承object，所以都是新式类

#经典类和新式类最大区别就在于有没有继承object
# class A():
#     pass
#
# class B:
#     pass
#
# class C(object):
#     pass
#
# class ATM():
#     money = 50000
#     #self 代表实例本身
#     def draw_money(self, getmoney):
#         if getmoney <= self.money:
#             #实例的money   类的money
#             #self.money = self.money - getmoney
#             self.money -= getmoney
#             print(f"取了{getmoney},还剩余{self.money}")
#         else:
#             print("atm余额不足")
# #实例化
# atm1 = ATM()
# atm2 = ATM()
# #属性和方法的访问
# atm1.draw_money(1000)
# atm2.draw_money(10000)
# print(atm1.money, atm2.money)
# atm1.money = 60000
# print(atm1.money, atm2.money)
# atm1.area = "长沙"
# atm2.area = "常德"
# print(dir(atm1), dir(atm2))
# print(ATM.money)
# ATM.area = "湖南"
# print(ATM.area)
# del atm1.area
# print(atm1.area)

######类空间和实例空间#######
#类创建的时候会生成类空间
#实例化对象的时候就会生成实例空间，不同的实例，空间都是独立的
#实例查找属性方法的时候，先在自己的实例空间找，找不到就是类空间查找，
#  类空间找不到就去父类找，一层一层往上找

#为什么实例可以访问类属性？
#创建实例的时候，会有一个类对象指针，通过这个指针，实例就能访问类的属性方法了

############__init__方法
#实例对象的构造方法（初始化方法）
#实例化对象的时候就会自动调用__init__方法
class ATM():
    money = 50000
    #self 代表实例本身
    def __init__(self,area):
        self.area = area
        self.bank = "jianshe"
    def draw_money(self, getmoney):
        if getmoney <= self.money:
            #实例的money   类的money
            #self.money = self.money - getmoney
            self.money -= getmoney
            print(f"取了{getmoney},还剩余{self.money}")
        else:
            print("atm余额不足")

atm1 = ATM("changsha")
atm2 = ATM("changde")
print(atm1.draw_money(100))

##########__new__方法
#创建实例，一般情况下不需要重写
# class ATM():
#     money = 50000
#     #self 代表实例本身
#     def __init__(self,area):
#         print("this is init")
#         self.area = area
#         self.bank = "jianshe"
#     def __new__(cls,*args,**kwargs):
#         print("this is new method:",cls)
#         # print(args, kwargs)
#         return object.__new__(cls)
#
#     def draw_money(self, getmoney):
#         if getmoney <= self.money:
#             #实例的money   类的money
#             #self.money = self.money - getmoney
#             self.money -= getmoney
#             print(f"取了{getmoney},还剩余{self.money}")
#         else:
#             print("atm余额不足")
#
# atm1 = ATM("changsha")
# print(atm1)

#总结：
#__new__是创建实例的方法
#__init__对创建好的实例进行初始化工作的方法

#__new__方法必须要传入一个参数(cls)，代表当前类
#__new__必须要返回一个实例化对象
#__init__的self就表示__new__方法返回的实例，__init__就对这个实例进行初始化工作
#子类没有定义__new__，就会去找父类的__new__
#新式类才有__new__
#如果实例化对象和本身class不一致， __init__就不会执行

#__new__方法属于静态方法
#__init__方法是实例方法

#单例模式
#无论实例化多少次，都只返回同一个对象实例
#重写__new__

# a1 = ATM()
# a2 = ATM()

class A():
    obj = None
    def __new__(cls, *args, **kwargs):
        if not A.obj:
            A.obj = object.__new__(cls)
        return A.obj
a1 = A()
a2 = A()
print(a1,a2)
print(id(a1),id(a2))